/**
 * Octopus, an XMMS2 client.
 * Copyright (C) 2014 Octopus Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

namespace OctopusUi {
	public class UiAlbumArt : Mx.Frame {
		private int                    _albumArtSize;
		private bool                   _use_texture_cache;
		private string                 _picture_front;
		private Octopus.AlbumArtLoader albumArtLoader;
		private Mx.Image               albumArt;
		private Mx.Stack               albumArtStack;
		public  Mx.Label               defaultAlbumArtArtist;
		public  Mx.Label               defaultAlbumArtAlbum;

		public signal void album_art_loaded ();

		public UiAlbumArt (int albumArtSize, bool use_texture_cache) {
			this._albumArtSize  = albumArtSize;
			this._use_texture_cache = use_texture_cache;
			this.albumArtLoader = new Octopus.AlbumArtLoader ();
			this.albumArtLoader.bindata.connect (() => {
				Gdk.Pixbuf pixbuf = null;
				//process xmms bindata
				try {
					var loader = new Gdk.PixbufLoader();
					loader.write(this.albumArtLoader.get_bindata ());
					loader.close();
					//we may want to scale
					//var unscaled = loader.get_pixbuf();
					//pixbuf = unscaled.scale_simple (150, 150, /*GdkPixbuf.InterpType.bilinear*/ 2);
					pixbuf = loader.get_pixbuf();
				} catch (GLib.Error e) {
					GLib.warning ("error: %s", e.message);
					this.album_art_loaded ();
				}
				if (pixbuf != null) {
					setFromPixbuf (pixbuf);
					if (_use_texture_cache)
						OctopusMx.Utils.texture_cache_insert (_picture_front, pixbuf);
				} else {
					this.album_art_loaded ();
				}
			});

			this.albumArtStack = new Mx.Stack ();
			this.albumArtStack.name = "albumArt-background";
			this.add_child (this.albumArtStack);

			//defalt album art, we always show this, in case something goes wrong
			var defaultAlbumArt = new Mx.BoxLayout ();
			defaultAlbumArt.style_class = "albumArt-default";
			defaultAlbumArt.orientation = Mx.Orientation.VERTICAL;
			defaultAlbumArt.width = this._albumArtSize;
			defaultAlbumArt.height = this._albumArtSize;
			defaultAlbumArt.x_align = Clutter.ActorAlign.START;
			defaultAlbumArt.y_align = Clutter.ActorAlign.START;
			this.defaultAlbumArtArtist = new Mx.Label ();
			this.defaultAlbumArtArtist.style_class = "albumArt-default-artist";
			defaultAlbumArt.add_child (this.defaultAlbumArtArtist);
			this.defaultAlbumArtAlbum = new Mx.Label ();
			this.defaultAlbumArtAlbum.style_class = "albumArt-default-album";
			this.defaultAlbumArtAlbum.line_wrap = true;
			defaultAlbumArt.add_child (this.defaultAlbumArtAlbum);
			this.albumArtStack.add_child (defaultAlbumArt);
			this.albumArt = new Mx.Image ();
			this.albumArt.style_class = "albumArt-image";
			this.albumArt.width = this._albumArtSize;
			this.albumArt.height = this._albumArtSize;
			this.albumArt.scale_mode = Mx.ImageScaleMode.FIT;
			this.albumArt.x_align = Clutter.ActorAlign.START;
			this.albumArt.y_align = Clutter.ActorAlign.START;
			this.albumArt.visible = false;
			this.albumArtStack.add_child (this.albumArt);

			var albumArtOverlay = new Mx.Frame ();
			albumArtOverlay.name = "albumArt-overlay";
			this.albumArtStack.add_child (albumArtOverlay);
		}

		public void loadAlbumArt (string picture_front) {
			this.albumArt.visible = false;

			if (   (picture_front == null)
			    || (picture_front == "")) {
				this.album_art_loaded ();
				return;
			}
			_picture_front = picture_front;
			var filename = GLib.Path.build_filename (Octopus.Global.get ().bindata_path, picture_front);
			//step 1: check if picture_front is already in textureCache
			if (   _use_texture_cache
			    && Mx.TextureCache.get_default ().contains (picture_front)) {
				setFromTextureCache (picture_front);
				return;
			}
			//step 2: load from filesystem
			try {
				var pixbuf = new Gdk.Pixbuf.from_file (filename);
				setFromPixbuf (pixbuf);
				if (_use_texture_cache)
					OctopusMx.Utils.texture_cache_insert (picture_front, pixbuf);
			} catch (GLib.Error e) {
				//step 3: load from xmms
				this.albumArtLoader.xmms_bindata_retrieve (picture_front);
			}
		}

		private void setFromTextureCache (string picture_front) {
			try {
				this.albumArt.set_from_file_at_size (picture_front, -1, -1);
				this.albumArt.width = this._albumArtSize;
				this.albumArt.height = this._albumArtSize;
				this.albumArt.visible = true;
			} catch (GLib.Error e) {
				GLib.warning ("error loading albumArt from Mx.TextureCache; name: " + picture_front + " message: " + e.message);
			} finally {
				this.album_art_loaded ();
			}
		}

		private void setFromPixbuf (Gdk.Pixbuf pixbuf) {
			try {
				this.albumArt.set_from_data (pixbuf.get_pixels (),
				                             pixbuf.has_alpha ? Cogl.PixelFormat.RGBA_8888
				                                              : Cogl.PixelFormat.RGB_888,
				                             pixbuf.width,
				                             pixbuf.height,
				                             pixbuf.rowstride);
				this.albumArt.width = this._albumArtSize;
				this.albumArt.height = this._albumArtSize;
				this.albumArt.visible = true;
			} catch (GLib.Error e) {
				GLib.warning ("error loading albumArt; name: %s message: %s", _picture_front, e.message);
			} finally {
				this.album_art_loaded ();
			}
		}
	}
}
